#include <jni.h>
#include <string>
#include "JavaCall.h"
#include "WlFFmpeg.h"

#include "android/log.h"

#define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR,"(><)",format, ##__VA_ARGS__);

JavaVM *javaVM;
JavaCall *javaCall;
WlFFmpeg *fFmpeg = NULL;
WlPlayStat *playStat;
bool isExiting = false;
pthread_t pthread;
jobject pJobject;
jclass pJclass;
jmethodID pID;
extern "C"
JNIEXPORT jint JNICALL
Java_com_cql_cqaudio_Wlplay_n_1seek(JNIEnv *env, jobject instance, jint seconds) {

    // TODO
    if (fFmpeg != NULL) {
        fFmpeg->seek(seconds);
    }
    return 1;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_cql_cqaudio_Wlplay_n_1stop(JNIEnv *env, jobject instance) {

    // TODO
    if (isExiting) {
        return 0;
    }

    isExiting = true;
    if (fFmpeg != NULL) {
        fFmpeg->release();
        delete (fFmpeg);
        fFmpeg = NULL;
        if (javaCall != NULL) {
            delete (javaCall);
            javaCall = NULL;
        }
        if (playStat != NULL) {
            delete (playStat);
            playStat = NULL;
        }
    }
    isExiting = false;
    pJobject= env->NewGlobalRef(instance);

    pJclass= env->GetObjectClass(pJobject);
    pID= env->GetMethodID(pJclass, "onCallNextAudio", "()V");
    env->CallVoidMethod(pJobject,pID);
    return 0;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_cql_cqaudio_Wlplay_wlPause(JNIEnv *env, jobject instance) {

    // TODO
    if (fFmpeg != NULL) {
        fFmpeg->pause();
    }
    return 1;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_cql_cqaudio_Wlplay_wlResume(JNIEnv *env, jobject instance) {

    // TODO
    if (fFmpeg != NULL) {
        fFmpeg->resume();
    }
    return 1;
}

extern "C"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    jint result = -1;
    javaVM = vm;
    JNIEnv *env;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        LOGE("GetEnv failed!");

        return result;
    }
    LOGE("GetEnv success!");
    return JNI_VERSION_1_4;
};



extern "C"
JNIEXPORT jint JNICALL
Java_com_cql_cqaudio_Wlplay_onPrepared(JNIEnv *env, jobject instance, jstring url_) {
    const char *url = env->GetStringUTFChars(url_, 0);
    if (fFmpeg == NULL) {
        // TODO
        if (javaCall == NULL) {
            javaCall = new JavaCall(javaVM, env, instance);
            LOGE("create_javacall");
        }
        javaCall->onCallLoad(MAIN_THREAD, true);
        playStat = new WlPlayStat;
        fFmpeg = new WlFFmpeg(playStat, javaCall, url);
        fFmpeg->prepared();

        //env->ReleaseStringUTFChars(url_, url);
    }

    return 1;
}

void *startDecode(void *cotnext) {
    WlFFmpeg *wlFFmpeg = (WlFFmpeg*)cotnext;
    wlFFmpeg->start();
    pthread_exit(&pthread);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_cql_cqaudio_Wlplay_n_1pitch(JNIEnv *env, jobject instance, jfloat n_pitch) {

    // TODO
    if (fFmpeg!=NULL){
        fFmpeg->setPitch(n_pitch);
    }

}
extern "C"
JNIEXPORT void JNICALL
Java_com_cql_cqaudio_Wlplay_n_1tempo(JNIEnv *env, jobject instance, jfloat n_tempo) {

    // TODO
    if (fFmpeg!=NULL){
        fFmpeg->setTempo(n_tempo);
    }

}

extern "C"
JNIEXPORT jint JNICALL
Java_com_cql_cqaudio_Wlplay_n_1muter(JNIEnv *env, jobject instance, jint channels) {

    // TODO
    if (fFmpeg!=NULL){
        fFmpeg->setMuter(channels);
    }
    return 0;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_cql_cqaudio_Wlplay_n_1setVolume(JNIEnv *env, jobject instance,jint process) {

    // TODO
    if (fFmpeg!=NULL){
        fFmpeg->setVolume(process);
    }
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_cql_cqaudio_Wlplay_n_1getDuration(JNIEnv *env, jobject instance) {

    // TODO
    if (fFmpeg!=NULL){
        return fFmpeg->duration;
    }
    return 0;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_cql_cqaudio_Wlplay_start(JNIEnv *env, jobject instance) {

    // TODO
    if (fFmpeg != NULL) {
        pthread_create(&pthread, NULL, startDecode, fFmpeg);
        //   fFmpeg->start();
    }

    return 1;

}
